use std::fs;
use std::path::Path;
use tauri::command;
use crate::models::dataset::{Dataset, ValidationResult};

#[command]
pub async fn save_dataset(path: String, data: String) -> Result<(), String> {
    // 验证路径
    let file_path = Path::new(&path);
    
    // 确保父目录存在
    if let Some(parent) = file_path.parent() {
        if !parent.exists() {
            fs::create_dir_all(parent)
                .map_err(|e| format!("无法创建目录: {}", e))?;
        }
    }

    // 验证JSON格式
    match serde_json::from_str::<serde_json::Value>(&data) {
        Ok(_) => {},
        Err(e) => return Err(format!("无效的JSON格式: {}", e))
    }

    // 格式化JSON（美化输出）
    let parsed: serde_json::Value = serde_json::from_str(&data)
        .map_err(|e| format!("JSON解析失败: {}", e))?;
    
    let formatted_data = serde_json::to_string_pretty(&parsed)
        .map_err(|e| format!("JSON格式化失败: {}", e))?;

    // 写入文件
    fs::write(&path, formatted_data)
        .map_err(|e| format!("写入文件失败: {}", e))?;

    Ok(())
}

#[command]
pub async fn load_dataset(path: String) -> Result<String, String> {
    // 检查文件是否存在
    let file_path = Path::new(&path);
    if !file_path.exists() {
        return Err("文件不存在".to_string());
    }

    // 读取文件内容
    let content = fs::read_to_string(&path)
        .map_err(|e| format!("读取文件失败: {}", e))?;

    // 验证JSON格式
    let _: serde_json::Value = serde_json::from_str(&content)
        .map_err(|e| format!("文件不是有效的JSON格式: {}", e))?;

    Ok(content)
}

#[command]
pub async fn validate_dataset(data: String) -> Result<ValidationResult, String> {
    // 首先验证JSON格式
    let parsed_data: serde_json::Value = serde_json::from_str(&data)
        .map_err(|e| format!("JSON解析失败: {}", e))?;

    // 尝试解析为数据集格式
    let dataset = match serde_json::from_value::<Vec<crate::models::dataset::Conversation>>(parsed_data.clone()) {
        Ok(conversations) => Dataset { conversations },
        Err(_) => {
            // 尝试解析为单个对话
            match serde_json::from_value::<crate::models::dataset::Conversation>(parsed_data) {
                Ok(conversation) => {
                    let mut dataset = Dataset::new();
                    dataset.add_conversation(conversation);
                    dataset
                },
                Err(e) => {
                    return Ok(ValidationResult {
                        is_valid: false,
                        errors: vec![format!("数据格式不符合ShareGPT规范: {}", e)],
                        warnings: vec![]
                    });
                }
            }
        }
    };

    // 验证数据集内容
    Ok(dataset.validate())
}

#[command]
pub async fn get_file_info(path: String) -> Result<FileInfo, String> {
    let file_path = Path::new(&path);
    
    if !file_path.exists() {
        return Err("文件不存在".to_string());
    }

    let metadata = fs::metadata(&path)
        .map_err(|e| format!("无法获取文件信息: {}", e))?;

    let size = metadata.len();
    let modified = metadata.modified()
        .map_err(|e| format!("无法获取修改时间: {}", e))?;

    // 尝试获取文件名
    let file_name = file_path.file_name()
        .and_then(|n| n.to_str())
        .unwrap_or("未知文件")
        .to_string();

    Ok(FileInfo {
        name: file_name,
        size,
        modified: modified.duration_since(std::time::UNIX_EPOCH)
            .unwrap_or_default()
            .as_secs(),
        path: path.clone(),
    })
}

#[command]
pub async fn check_file_exists(path: String) -> Result<bool, String> {
    Ok(Path::new(&path).exists())
}

#[command]
pub async fn create_backup(path: String) -> Result<String, String> {
    let file_path = Path::new(&path);
    
    if !file_path.exists() {
        return Err("原文件不存在".to_string());
    }

    // 生成备份文件名
    let backup_path = if let Some(extension) = file_path.extension() {
        format!("{}.backup.{}", 
            file_path.with_extension("").to_string_lossy(),
            extension.to_string_lossy())
    } else {
        format!("{}.backup", path)
    };

    // 复制文件
    fs::copy(&path, &backup_path)
        .map_err(|e| format!("创建备份失败: {}", e))?;

    Ok(backup_path)
}

#[derive(serde::Serialize)]
pub struct FileInfo {
    pub name: String,
    pub size: u64,
    pub modified: u64, // Unix timestamp
    pub path: String,
} 